package org.nf.trading.util;

import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Slf4j
public class JwtUtils {

    /**
     * 秘钥，用于signature（签名）部分的加密和解密
     */
    private static final String KEY = "nf-it";
    /**
     * 签发机构
     */
    private static final String ISS = "nf";

    /**
     * 创建token
     * @param claims 数据载体
     * @param ttl token的过期时间
     * @return
     */
    public static String createToken(Map<String, Object> claims, long ttl) {
        JwtBuilder builder = Jwts.builder()
                //获取签名秘钥，并采用HS256的加密算法进行提签名
                .signWith(SignatureAlgorithm.HS256, KEY)
                //jwt唯一标识
                .setId(UUID.randomUUID().toString())
                //设置数据内容
                .setClaims(claims)
                //设置签发人
                .setIssuer(ISS)
                //主题
                .setSubject("JWT AUTH")
                //签发时间
                .setIssuedAt(new Date());
        //设置过期时间
        if(ttl > 0) {
            builder.setExpiration(getExpDate(ttl));
        }
        //创建jwt字符串并返回
        return builder.compact();
    }

    /**
     * 获取载体的数据
     * @param token jwt
     * @param name json载体数据中的name
     * @param type 载体数据的类型
     * @return
     * @param <T>
     */
    public static <T> T getPayload(String token, String name, Class<T> type) {
        return Jwts.parser()
                //解密
                .setSigningKey(KEY)
                //解析token中的数据载体部分
                .parseClaimsJws(token)
                //取出载体数据
                .getBody()
                //根据name和type取中相应的value
                .get(name, type);
    }

    /**
     * 验证token的有效性，如果验证不通过会抛出相应的异常
     * @param token
     */
    public static void verify(String token) {
        Jwts.parser().setSigningKey(KEY).parseClaimsJws(token);
    }

    /**
     * 根据用户传的ttl计算出过期时间
     * @param ttl
     * @return
     */
    private static Date getExpDate(long ttl) {
        //当前时间 + ttl = 过期时间
        Date expDate = new Date(System.currentTimeMillis() + ttl);
        log.debug("Token过期时间：" + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(expDate));
        return expDate;
    }
}
